﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Text.RegularExpressions;
using MoneyWentWhere.DataModel.Binding;

namespace MoneyWentWhere.DataModel
{
    public class TransferTxSettings : TxSettings
    {
        public override TransactionKind Kind
        {
            get { return TransactionKind.Transfer; }
        }
        public string AccountName;
        public Account Account;

        public bool AmountSpecified;
        public decimal Amount;
        public Currency ToCurrency;

        public TransferTxSettings(String accountName)
        {
            if (accountName == null) { accountName = ""; }

            AccountName = accountName.Trim();
            AmountSpecified = false;
        }

        public TransferTxSettings(Account account)
            : this(account.Name)
        {
            Account = account;
        }

        public TransferTxSettings(String accountName, decimal amount, Currency toCurrency)
        {
            AccountName = accountName.Trim();

            AmountSpecified = true;
            Amount = amount;
            ToCurrency = toCurrency;
        }
        public TransferTxSettings(Account account, decimal amount)
            : this (account.Name, amount, account.Currency)
        {
            Account = account;
        }

        new public static TransferTxSettings Parse(String rep)
        {
            rep = rep.RemovePrefix(TransferPrefix);

            int pos = rep.LastIndexOf("(");
            if (pos < 0)
            {
                return new TransferTxSettings(rep);
            }
            else 
            {
                String acctName = rep.Substring(0, pos);
                decimal amount;
                if (TryExtractNumber(rep.Substring(pos), out amount))
                {
                    // TODO: Try to extract currency
                    // If this fails, doesn't matter, 
                    // can get it from account anyway
                    return new TransferTxSettings(acctName, amount, null); 
                }
                return new TransferTxSettings(acctName);
            }
        }

        public override string ToRepString()
        {
            String rep = TransferPrefix + AccountName;
            if (AmountSpecified)
            {
                rep += " (" + 
                    (ToCurrency == null ? "" : ToCurrency + " ") +
                    Math.Abs(Amount).ToString("N2") + 
                    ")";
            }
            return rep;
        }

        new internal static TransferTxSettings Create(Transaction t)
        {
            if (t.TransferToTx == null) { return null; }

            if (t.Account.Currency == t.TransferToTx.Account.Currency)
            {
                return new TransferTxSettings(t.TransferToTx.Account);
            }
            else
            {
                return new TransferTxSettings(t.TransferToTx.Account,
                    t.TransferToTx.Amount);
            }
        }

        protected override void ApplyCore(Transaction t)
        {
            if (Account == null)
            {
                Account = t.DataSet.Accounts[AccountName];
                if (Account == null) { throw new ArgumentException("No account: " + AccountName); }
            }
            if (AmountSpecified && t.Account.Currency != Account.Currency)
            {
                // Invert the sign if necessary
                decimal toAmount = Math.Abs(Amount);
                if (t.Amount > 0) { toAmount = -toAmount; }

                t.TransferCreate(Account, toAmount);
            }
            else
            {
                // TODO: warn if AmountSpecified but currencies were the same

                t.TransferCreate(Account);
            }
        }

        public void FillAutoComplete(
            IList list, out int selectedIndex, Transaction tx, bool useFilter)
        {
            String filter = "";
            if (useFilter)
            {
                filter = AccountName;
                if (filter == null) { filter = ""; }
                filter = filter.Trim();
            }

            selectedIndex = -1;
            for (int i = 0; i < tx.DataSet.Accounts.Count; i++)
            {
                Account acct = tx.DataSet.Accounts[i];
                if (tx.Account == acct) { continue; }

                // Apply filter
                if (!useFilter ||
                    acct.Name.StartsWith(filter,
                        StringComparison.CurrentCultureIgnoreCase)) 
                {
                    list.Add(acct);
                }

                if (AccountName == acct.Name)
                {
                    selectedIndex = list.Count - 1;
                }
            }

            // Select the best match (shortest for now).
            if (selectedIndex == -1)
            {
                if (filter == "" && list.Count > 0) { selectedIndex = 0; }
                else
                {
                    int minLength;
                    selectedIndex = IndexOfMinLengthItem(list, out minLength);
                }
            }
        }
    }
}
